package com.xdog.okx.utils;

import lombok.extern.slf4j.Slf4j;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * OKX API签名工具类
 */
@Slf4j
public class OkxSignatureUtils {

    private static final String ALGORITHM = "HmacSHA256";
    private static final DateTimeFormatter DATE_TIME_FORMATTER =
        DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").withZone(ZoneOffset.UTC);

    /**
     * 生成OKX API签名
     *
     * @param timestamp   时间戳 ISO格式
     * @param method      HTTP方法 (GET/POST/PUT/DELETE)
     * @param requestPath 请求路径 (不含host部分)
     * @param body        请求体 (GET请求可以为空)
     * @param secretKey   API Secret Key
     * @return 签名字符串
     */
    public static String generateSignature(String timestamp, String method, String requestPath, String body, String secretKey) {
        try {
            // 构建预签名字符串
            StringBuilder preHash = new StringBuilder();
            preHash.append(timestamp);
            preHash.append(method.toUpperCase());
            preHash.append(requestPath);

            // 对于GET请求，body应该是一个空字符串而不是null
            if (body != null) {
                preHash.append(body);
            } else if (method.equalsIgnoreCase("GET")) {
                preHash.append("");
            }

            // 使用HMAC SHA256算法签名
            Mac mac = Mac.getInstance(ALGORITHM);
            SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), ALGORITHM);
            mac.init(secretKeySpec);

            byte[] hash = mac.doFinal(preHash.toString().getBytes(StandardCharsets.UTF_8));

            // 使用Base64编码
            return Base64.getEncoder().encodeToString(hash);
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            throw new RuntimeException("生成OKX API签名失败", e);
        }
    }

    /**
     * 生成当前时间戳
     *
     * @return ISO格式时间戳
     */
    public static String generateTimestamp() {
        String timestamp = DATE_TIME_FORMATTER.format(Instant.now());
        log.debug("生成时间戳: {}", timestamp);
        return timestamp;
    }

    /**
     * 生成带签名的请求头
     *
     * @param apiKey      API Key
     * @param secretKey   API Secret Key
     * @param passphrase  Passphrase
     * @param method      HTTP方法
     * @param requestPath 请求路径
     * @param body        请求体
     * @return 包含所有鉴权信息的Map
     */
    public static Map<String, String> generateAuthHeaders(String apiKey, String secretKey, String passphrase,
                                                          String method, String requestPath, String body) {
        // 检查必要参数是否为空
        if (apiKey == null || apiKey.isEmpty()) {
            throw new IllegalArgumentException("API Key不能为空，请检查sys_config表中的okx.api.key配置");
        }
        if (secretKey == null || secretKey.isEmpty()) {
            throw new IllegalArgumentException("Secret Key不能为空，请检查sys_config表中的okx.api.secret配置");
        }
        if (passphrase == null || passphrase.isEmpty()) {
            throw new IllegalArgumentException("Passphrase不能为空，请检查sys_config表中的okx.api.passphrase配置");
        }

        String timestamp = generateTimestamp();
        String signature = generateSignature(timestamp, method, requestPath, body, secretKey);

        Map<String, String> headers = new HashMap<>();
        headers.put("OK-ACCESS-KEY", apiKey);
        headers.put("OK-ACCESS-SIGN", signature);
        headers.put("OK-ACCESS-TIMESTAMP", timestamp);
        headers.put("OK-ACCESS-PASSPHRASE", passphrase);
        headers.put("Content-Type", "application/json");

        return headers;
    }
}
